
package horde.utils;

import java.io.File;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Properties;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

/**
 * @author Andres Picazo and Arturo Mazon
 * Takes all the information of any XML well formatted and generates a general tree of nodes with the information taken
 */
public class ParseXML {

    // <editor-fold defaultstate="collapsed" desc="Atributes">


    private HordeHandler hordeHandler;
    private Node parsedNode;

    // </editor-fold>
    public ParseXML(String pathToXML) {
        try {
            parsedNode = null;
            XMLReader parser = XMLReaderFactory.createXMLReader();
//            SAXParserFactory factory = SAXParserFactory.newInstance();
//            SAXParser parser = factory.newSAXParser();
            pathToXML = new RawLoader().getSystemPath(pathToXML);
            File f = new File (pathToXML);
            if (f.canRead()) {
                hordeHandler = new HordeHandler();
                parser.setContentHandler(hordeHandler);
                parser.parse(pathToXML);
//                parser.parse(f, hordeHandler);
                parsedNode = hordeHandler.root;
            } else throw new Exception ("Parse error");
        }
        catch (Exception e) {
            System.err.println ("Failure on parseXML");
        }        
    }

    public static Node parseFile (String pathToXML) {
        ParseXML parser = new ParseXML(pathToXML);
        return parser.getParsedRoot();
    }

    public Node getParsedRoot () {
        return parsedNode;
    }

    // <editor-fold defaultstate="collapsed" desc="NODE">

    /**
     * Creates a node with all the information required
     */
    public class Node {

        // <editor-fold defaultstate="collapsed" desc="Atributes">
        /**
         * Name of the current node
         */
        String name;
        Properties properties;
        /**
         * List of child nodes
         */
        ArrayList<Node> child_nodes;
        Node parent;
        int level;

        // </editor-fold>

        // <editor-fold defaultstate="collapsed" desc="Builder">
        public Node (String name, Node parent) {
            this.name = name;
            this.parent = parent;
            properties = new Properties();
            child_nodes = new ArrayList();
        }

        // </editor-fold>
        
        public void addProperty(String name, String value) {
            properties.put(name, value);
        }
        public void addNode (Node n) {
            child_nodes.add(n);
        }

        @Override public String toString () {
            String s = "--- Node: " + name + "(" + child_nodes.size() + ")---\n";
            if (!properties.isEmpty()) {
                Enumeration keys = properties.keys();
                while (keys.hasMoreElements()) {
                    String currentKey = (String)keys.nextElement();
                    s += currentKey+":"+properties.getProperty(currentKey) + "\n";
                }
            }
            for (Node child : child_nodes) s += child.toString();
            return s+= "--- END " + name + "---\n";
        }

        public String getProperty (String property) {
            if (properties.containsKey(property)) return (String)properties.get(property);
            else return null;
        }

        public Properties getProperties() {
            return properties;
        }

        public String getName () {
            return name;
        }

        public Node getParentNode () {
            return parent;
        }

        public ArrayList<Node> getChildNodes () {
            return child_nodes;
        }
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="XML Handler">

    /**
     * Creates the nodes
     */
    private class HordeHandler extends DefaultHandler {
        private Node root;
        private Node currentNode;

        public HordeHandler () {
            this.root = null;
            this.currentNode = null;
        }

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            /* The root node */
            if (root == null) {
                root = new Node(localName, null);
                currentNode = root;
            } else {
                Node newNode = new Node(localName, currentNode);
                currentNode = newNode;
                currentNode.parent.addNode(currentNode);
            }
            /* Add the properties */
            if (attributes != null && attributes.getLength() != 0) {
                for (int i = 0; i < attributes.getLength(); i++) {
                    currentNode.addProperty(attributes.getLocalName(i), attributes.getValue(i));
                }
            }
        }

        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if (localName.equals(currentNode.name)) {
                currentNode = currentNode.parent;

            }
        }
    }
    // </editor-fold>
}
